//
//  UIImage+YHPDFIcon.m
//  YHPDFImageLoader
//
//  Created by yaheng on 16/10/10.
//  Copyright © 2016年 yaheng. All rights reserved.
//

#import "UIImage+YHPDFIcon.h"
#import "YHPDFImagePath.h"
#import "YHPDFImageLoader.h"
#import "YHConfig.h"
#import "YHDispatch.h"

#define CheckString(str)    if (!str || !str.length) { \
                                return nil; \
                            }
#define YH_IS(obj, cls)                                 (obj != nil && [obj isKindOfClass:[cls class]])
#define YH_IS_STRING(obj)                               (YH_IS(obj, NSString))
#define YH_IS_VALID_STRING(obj)                       (YH_IS_STRING(obj) && [obj length])

@implementation UIImage (YHPDFIcon)

+ (UIImage *)yh_imageNamed:(NSString *)name {
    CheckString(name)
    
    UIImage *image = nil;
    image = [UIImage yh_imageWithPDFFileNamed:name];
    
    if (image) {
        return image;
    }else {
        return [self yh_getImageWithName:name];

    }
}

+ (UIImage *)yh_imageWithContentsOfFile:(NSString *)path {
    CheckString(path)
    
    UIImage *image = nil;
    image = [UIImage yh_imageWithPDFFileURL:[NSURL fileURLWithPath:path]];
    
    if (image) {
        return image;
    } else {
        return [self yh_getImageFormFilePath:path];
    }
}

+ (UIImage *)yh_imageWithPDFFileNamed:(NSString *)fileName {
    return [UIImage yh_imageWithPDFFileNamed:fileName expectSize:CGSizeZero];
}

+ (UIImage *)yh_imageWithPDFFileNamed:(NSString *)fileName expectSize:(CGSize)size {
    return [UIImage yh_imageWithPDFFileNamed:fileName expectSize:(CGSize)size canStretched:NO];
}

+ (UIImage *)yh_imageWithPDFFileNamed:(NSString *)fileName expectSize:(CGSize)size canStretched:(BOOL)stretched {
    CheckString(fileName)
    NSString *tempFileName = nil;
    if (![[fileName pathExtension] isEqualToString:@"pdf"]) {
        tempFileName = fileName;
        fileName = [fileName stringByDeletingPathExtension];
        fileName = [fileName stringByAppendingPathExtension:@"pdf"];
    }
    
    CGFloat scale = [UIScreen mainScreen].scale;
    size = CGSizeMake(size.width * scale, size.height * scale);
    
    NSURL *url = [YHPDFImagePath fileURLWithName:fileName];
    if (!url) {
        NSString *path = [[NSBundle mainBundle] pathForResource:tempFileName ofType:nil];
        if (!path) {
            path = [[NSBundle mainBundle] pathForResource:tempFileName ofType:nil inDirectory:YHFileDirectory];
        }

        UIImage *targetImage = nil;
        if (path) {
            targetImage = [self yh_getImageFormFilePath:path];
            
        } else {
            targetImage = [self yh_getImageWithName:tempFileName];
            
        }
        // 判断是否 == 控件size * scale的Size
        if (!CGSizeEqualToSize(size, targetImage.size) && targetImage) {
            
        } else {
            // log...
            return nil;
        }
    }
    return [YHPDFImageLoader getPDFImageWithURL:url size:size canStretched:stretched];
}

+ (UIImage *)yh_imageWithPDFFileURL:(NSURL *)fileURL {
    return [UIImage yh_imageWithPDFFileURL:fileURL expectSize:CGSizeZero];
}

+ (UIImage *)yh_imageWithPDFFileURL:(NSURL *)fileURL expectSize:(CGSize)size {
    return [UIImage yh_imageWithPDFFileURL:fileURL expectSize:size canStretched:NO];
}

+ (UIImage *)yh_imageWithPDFFileURL:(NSURL *)fileURL expectSize:(CGSize)size canStretched:(BOOL)stretched {
   return [YHPDFImageLoader getPDFImageWithURL:fileURL size:size canStretched:stretched];
}

// MARK: - 从路径中获取解压缩的图片
+ (UIImage *)yh_getImageFormFilePath:(NSString *)path {
    NSData *imageData = [NSData dataWithContentsOfFile:path];
    if (!imageData) {
        return nil;
    }
    
    UIImage *sourceImage = [[UIImage alloc] initWithData:imageData scale:[UIScreen mainScreen].scale];
    CGImageRef cgImage = YYCGImageCreateDecodedCopy(sourceImage.CGImage, YES);
    if (!cgImage) {
        return nil;
    }
    
    return [UIImage imageWithCGImage:cgImage scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];

}

// MARK: - 根据图片名来获取解压缩的图片
+ (UIImage *)yh_getImageWithName:(NSString *)name {
    CGImageRef cgImage = YYCGImageCreateDecodedCopy([UIImage imageNamed:name].CGImage, YES);
    if (!cgImage) {
        return nil;
    }

    return [UIImage imageWithCGImage:cgImage scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];
}

// MARK: - COPY FORM YYImageCoder
static CGImageRef YYCGImageCreateDecodedCopy(CGImageRef imageRef, BOOL decodeForDisplay) {
    if (!imageRef) return NULL;
    size_t width = CGImageGetWidth(imageRef);
    size_t height = CGImageGetHeight(imageRef);
    if (width == 0 || height == 0) return NULL;
    
    @autoreleasepool{
        if (decodeForDisplay) { //decode with redraw (may lose some precision)
            CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef) & kCGBitmapAlphaInfoMask;
            BOOL hasAlpha = NO;
            if (alphaInfo == kCGImageAlphaPremultipliedLast ||
                alphaInfo == kCGImageAlphaPremultipliedFirst ||
                alphaInfo == kCGImageAlphaLast ||
                alphaInfo == kCGImageAlphaFirst) {
                hasAlpha = YES;
            }
            // BGRA8888 (premultiplied) or BGRX8888
            // same as UIGraphicsBeginImageContext() and -[UIView drawRect:]
            CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;
            bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
            CGContextRef context = CGBitmapContextCreate(NULL,
                                                         width,
                                                         height,
                                                         8,
                                                         0,
                                                         CGColorSpaceCreateDeviceRGB(),
                                                         bitmapInfo);
            if (!context) return NULL;
            CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); // decode
            CGImageRef newImage = CGBitmapContextCreateImage(context);
            CFRelease(context);
            return newImage;
            
        } else {
            CGColorSpaceRef space = CGImageGetColorSpace(imageRef);
            size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
            size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
            size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
            CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
            if (bytesPerRow == 0 || width == 0 || height == 0) return NULL;
            
            CGDataProviderRef dataProvider = CGImageGetDataProvider(imageRef);
            if (!dataProvider) return NULL;
            CFDataRef data = CGDataProviderCopyData(dataProvider); // decode
            if (!data) return NULL;
            
            CGDataProviderRef newProvider = CGDataProviderCreateWithCFData(data);
            CFRelease(data);
            if (!newProvider) return NULL;
            
            CGImageRef newImage = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, space, bitmapInfo, newProvider, NULL, false, kCGRenderingIntentDefault);
            CFRelease(newProvider);
            return newImage;
        }
    }
}

// 子线程强制解压缩 || 加载图片 >>>> ================================================================================== //
+ (void)yh_imageNamed:(NSString *)name imageBlock:(loadImageForNameBlock)imageBlock {
    __weak typeof(self) weakSelf = self;
    dispatch_async([YHDispatch imageQueue], ^{
        UIImage *image = [weakSelf yh_imageNamed:name];
        if (imageBlock) {
            dispatch_async(dispatch_get_main_queue(), ^{
                imageBlock(image);
            });
        }
    });
}

+ (void)yh_imageWithPDFFileNamed:(NSString *)fileName imageBlock:(loadImageForNameBlock)imageBlock {
    [self yh_imageWithPDFFileNamed:fileName expectSize:CGSizeZero imageBlock:imageBlock];
}

+ (void)yh_imageWithPDFFileNamed:(NSString *)fileName expectSize:(CGSize)size imageBlock:(loadImageForNameBlock)imageBlock {
    [self yh_imageWithPDFFileNamed:fileName expectSize:(CGSize)size canStretched:NO imageBlock:imageBlock];
}

+ (void)yh_imageWithPDFFileNamed:(NSString *)fileName expectSize:(CGSize)size canStretched:(BOOL)stretched imageBlock:(loadImageForNameBlock)imageBlock {
    
    __weak typeof(self) weakSelf = self;
    dispatch_async([YHDispatch imageQueue], ^{
        UIImage *image = [weakSelf yh_imageWithPDFFileNamed:fileName expectSize:size canStretched:stretched];
        if (imageBlock) {
            dispatch_async(dispatch_get_main_queue(), ^{
                imageBlock(image);
            });
        }
    });

}

+ (void)yh_imageWithContentsOfFile:(NSString *)path imageBlock:(loadImageForNameBlock)imageBlock {
    __weak typeof(self) weakSelf = self;
    dispatch_async([YHDispatch imageQueue], ^{
        UIImage *image = [weakSelf yh_imageWithContentsOfFile:path];
        if (imageBlock) {
            dispatch_async(dispatch_get_main_queue(), ^{
                imageBlock(image);
            });
        }
    });

}

+ (void)yh_imageWithPDFFileURL:(NSURL *)fileURL imageBlock:(loadImageForNameBlock)imageBlock {
    [self yh_imageWithPDFFileURL:fileURL expectSize:CGSizeZero imageBlock:imageBlock];
}

+ (void)yh_imageWithPDFFileURL:(NSURL *)fileURL expectSize:(CGSize)size imageBlock:(loadImageForNameBlock)imageBlock {
    [self yh_imageWithPDFFileURL:fileURL expectSize:size canStretched:NO];
}

+ (void)yh_imageWithPDFFileURL:(NSURL *)fileURL expectSize:(CGSize)size canStretched:(BOOL)stretched imageBlock:(loadImageForNameBlock)imageBlock {
    dispatch_async([YHDispatch imageQueue], ^{
        UIImage *image = [YHPDFImageLoader getPDFImageWithURL:fileURL size:size canStretched:stretched];
        if (imageBlock) {
            dispatch_async(dispatch_get_main_queue(), ^{
                imageBlock(image);
            });
        }
    });

}

// >>> end ==================================================================================================== //

@end
